//	COPYRIGHT (C) 1980 BY BOARD OF TRUSTEES,
//	LELAND STANFORD JUNIOR UNIVERSITY

//APRIL 25, 1978
//BCPL-CONGEN, WRITTEN BY RAY CARHART.  THIS FILE CONTAINS THE FUNCTION
//WHICH MAKES PATTERN-RECORDS FOR USE IN THE GRAPH MATCHER.  THE ROUTINE
//BO (COMPUTES BOND ORDER IN A CTABLE ROW) IS USED ELSEWHERE, TOO.
LET BO(CTPTR,PTRTOP) = VALOF
// $( STATIC $( ORD = NIL; NBRNO = NIL $);
// ORD:=1;
// NBRNO:=CTABLE!CTPTR;
// WHILE CTPTR<PTRTOP DO
//  $(
//  CTPTR+:=1;
//  IF NBRNO NE CTABLE!CTPTR DO RESULTIS ORD;
//  ORD+:=1
//  $);
// RESULTIS ORD
// $);
 $[ $MOVE 2,CTPTR;
    $MOVE 3,2;
    $ADD 2,CTABLE;
    $HRR 1,2;
    $SUB 3,PTRTOP;
    $SOJ 3,0;
    $HRL 1,3;
    $MOVE 3,0(2);
    LP:
    $CAMN 3,1(1);
    $AOBJN 1,LP;
    $CAIG 1,0;
    $AOJ 1,0;
    $HRRZ 1,1;
    $SUB 1,2;
 $];

LET MAKEPATREC(PSTART,PSTOP,NTYPES,TYPENUMS,PTFLAG) = VALOF
 $( STATIC $( PNSCORE = NIL; MAXROWSZ = NIL; ANYCN = NIL; PNODE = NIL;
              ROWSZ = NIL; ORDPERM = NIL; NCE = NIL; NCN = NIL;
              SCRROW = NIL; TAGGEDNODE = NIL; ISOLATD = NIL; PTR = NIL;
              CTROW = NIL; PTRTOP = NIL; NCTROW = NIL; ONBR = NIL;
              PNBR = NIL; ROWRO = NIL; ICN = NIL; ICE = NIL; CN = NIL;
              CEN1 = NIL; CEN2 = NIL; NDOT= NIL; PATREC = NIL;
              NLNODES = NIL; LNODES = NIL; FROMNDS = NIL; FROMBOS = NIL;
              TONDS = NIL; TOBOS = NIL; PBO = NIL; CTPTR = NIL $);

 LET PNODESCORE(P,NTYPES,TYPENUMS) = VALOF
  $( STATIC $( NNONMATCH = NIL; ITYPE = NIL; NDOT = NIL; NNBRS = NIL;
               CTPTR = NIL; PTRTOP = NIL; NBR = NIL; ONBR = NIL $);
  NNONMATCH:=0;
  ITYPE:=0;
  WHILE ITYPE<NTYPES DO
   $(
   ITYPE+:=1;
   UNLESS TESTELEM(ITYPE,ATTYPE!P) DO NNONMATCH+:=TYPENUMS!ITYPE
   $);
  NDOT:=0;
  NNBRS:=0;
  ONBR:=0;
  CTPTR:=CTSTART!P-1;
  PTRTOP:=CTSTOP!P;
  WHILE CTPTR<PTRTOP DO
   $(
   CTPTR+:=1;
   NBR:=CTABLE!CTPTR;
   TEST ONBR=NBR THEN NDOT+:=1 OR NNBRS+:=1;
   ONBR:=NBR
   $);
  RESULTIS [NNONMATCH<<9]+[[NDOT+ARTYPE!P-1]<<6]+[NNBRS<<3]-HMAX!P+HMIN!P
  $);

 PNSCORE:=NEWVEC(PSTOP);
 MAXROWSZ:=0;
 ANYCN:=FALSE;
 PNODE:=PSTART-1;
 WHILE PNODE<PSTOP DO
  $(
  PNODE+:=1;
  PNSCORE!PNODE:=PNODESCORE(PNODE,NTYPES,TYPENUMS);
  ROWSZ:=CTSTOP!PNODE-CTSTART!PNODE;
  IF MAXROWSZ<ROWSZ DO MAXROWSZ:=ROWSZ;
  IF TESTELEM(0,ATTYPE!PNODE) DO ANYCN:=TRUE
  $);
 ORDPERM:=RANKORDER(PNSCORE,PSTART,PSTOP,FALSE);
 NCE:=0;
 NCN:=0;
 NLNODES:=0;
 SCRROW:=NEWVEC(MAXROWSZ+1);
 PNODE:=PSTART-1;
 WHILE PNODE<PSTOP DO
  $(
  PNODE+:=1;
  TEST LMINS!PNODE>0 THEN $( NLNODES+:=1; TAGGEDNODE:=FALSE $)
  OR
   TEST ANYCN THEN TAGGEDNODE:=TESTELEM(0,ATTYPE!PNODE)
   OR $( FLIPELEM(0,ATTYPE!PNODE); TAGGEDNODE:=TRUE $);
  ISOLATD:=TRUE;
  PTR:=CTSTART!PNODE-1;
  CTROW:=CTABLE+PTR;
  PTRTOP:=CTSTOP!PNODE;
  NCTROW:=PTRTOP-PTR;
  ONBR:=0;
  NDOT:=0;
  WHILE PTR<PTRTOP DO
   $(
   PTR+:=1;
   PNBR:=CTABLE!PTR;
   TEST PNBR<0 THEN $( PNBR:=-PNBR; CTABLE!PTR:=-[ORDPERM!PNBR] $)
   OR CTABLE!PTR:=ORDPERM!PNBR;
   IF ONBR=PNBR DO $( NDOT+:=1; LOOP $);
   ONBR:=PNBR;
   IF TAGGEDNODE DO
    IF (ANYCN -> TESTELEM(0,ATTYPE!PNBR),LMINS!PNBR=0) DO
     $( NCE+:=1; ISOLATD:=FALSE $)
   $);
  ROWRO:=RANKORDER(CTROW,1,NCTROW,TRUE);
  INVPERMUTE(CTROW,ROWRO,SCRROW,1,NCTROW);
  FREEVEC(ROWRO);
  DOTS!PNODE:=NDOT;
  IF TAGGEDNODE BITAND ISOLATD DO NCN+:=1
  $);
 FREEVEC(SCRROW);
 INVPERMUTE(ARTYPE,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(DOTS,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(HMIN,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(HMAX,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(ATTYPE,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(ATTYPEH,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(CTSTART,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(CTSTOP,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(LMINS,ORDPERM,PNSCORE,PSTART,PSTOP);
 INVPERMUTE(LMAXS,ORDPERM,PNSCORE,PSTART,PSTOP);
 FREEVEC(ORDPERM);
 FREEVEC(PNSCORE);
 NCE:=NCE>>1;
 ICN:=0;
 ICE:=0;
 CN:=NEWVEC(NCN);
 CEN1:=NEWVEC(NCE);
 CEN2:=NEWVEC(NCE);
 LNODES:=NEWVEC(NLNODES);
 FROMNDS:=NEWVEC(NLNODES);
 FROMBOS:=NEWVEC(NLNODES);
 TONDS:=NEWVEC(NLNODES);
 TOBOS:=NEWVEC(NLNODES);
 LNODES!0:=NLNODES;
 NLNODES:=0;
 PNODE:=PSTART-1;
 WHILE PNODE<PSTOP DO
  $(
  PNODE+:=1;
  TEST LMINS!PNODE>0 THEN
   $(
   MAPPEDTO!PNODE:=-2;
   NLNODES+:=1;
   LNODES!NLNODES:=PNODE;
   CTPTR:=CTSTART!PNODE;
   PTRTOP:=CTSTOP!PNODE;
   PNBR:=CTABLE!CTPTR;
   TEST PNBR<0 THEN $( PBO:=-1; PNBR:=-PNBR; CTPTR+:=1 $)
   OR $( PBO:=BO(CTPTR,PTRTOP); CTPTR+:=PBO $);
   FROMNDS!NLNODES:=PNBR;
   FROMBOS!NLNODES:=PBO;
   TEST CTPTR>PTRTOP THEN
    $(
    TONDS!NLNODES:=PNBR;
    TOBOS!NLNODES:=0;
    IF PBO>1 BITAND LMAXS!PNODE>1 DO DOTS!PNBR-:=1
    $)
   OR
    $(
    PNBR:=CTABLE!CTPTR;
    TEST PNBR<0 THEN $( TOBOS!NLNODES:=-1; TONDS!NLNODES:=-PNBR $)
    OR $( TOBOS!NLNODES:=PTRTOP-CTPTR+1; TONDS!NLNODES:=PNBR $);
    $)
   $)
  OR
   $(
   UNLESS TESTELEM(0,ATTYPE!PNODE) DO LOOP;
   ONBR:=0;
   ISOLATD:=TRUE;
   PTR:=CTSTART!PNODE-1;
   PTRTOP:=CTSTOP!PNODE;
   WHILE PTR<PTRTOP DO
    $(
    PTR+:=1;
    PNBR:=ABS[CTABLE!PTR];
    IF ONBR=PNBR DO LOOP;
    ONBR:=PNBR;
    UNLESS TESTELEM(0,ATTYPE!PNBR) DO LOOP;
    ISOLATD:=FALSE;
    IF PNBR>PNODE DO LOOP;
    ICE+:=1;
    CEN1!ICE:=PNODE;
    CEN2!ICE:=PNBR
    $);
   IF ISOLATD DO $( ICN+:=1; CN!ICN:=PNODE $)
   $)
  $);
 PATREC:=NEWVEC(13);
 PATREC!1:=PSTART;
 PATREC!2:=PSTOP;
 PATREC!3:=NCE;
 PATREC!4:=CEN1;
 PATREC!5:=CEN2;
 PATREC!6:=NCN;
 PATREC!7:=CN;
 PATREC!8:=LNODES;
 PATREC!9:=FROMNDS;
 PATREC!10:=FROMBOS;
 PATREC!11:=TONDS;
 PATREC!12:=TOBOS;
 PATREC!13:=PTFLAG;
 RESULTIS PATREC
 $);
